home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / remin301.zip / REMIN300.ZIP / DOSUBST.C < prev    next >
C/C++ Source or Header  |  1992-11-10  |  10KB  |  409 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  DOSUBST.C                                                  */
  4. /*                                                             */
  5. /*  This performs all the "%" substitution functions when      */
  6. /*  reminders are triggered.                                   */
  7. /*                                                             */
  8. /*  This file is part of REMIND.                               */
  9. /*  Copyright (C) 1992 by David F. Skoll.                      */
  10. /*                                                             */
  11. /***************************************************************/
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include "config.h"
  15. #ifdef HAVE_STDLIB_H
  16. #include <stdlib.h>
  17. #endif
  18. #ifdef HAVE_MALLOC_H
  19. #include <malloc.h>
  20. #endif
  21. #include "globals.h"
  22. #include "err.h"
  23. #include "types.h"
  24. #include "protos.h"
  25.  
  26. #define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
  27. #define ABS(x) ( (x) < 0 ? -(x) : (x) )
  28. #ifndef NL
  29. #define NL "\n"
  30. #endif
  31.  
  32. static char TODAY[] = "today";
  33. static char TOMORROW[] = "tomorrow";
  34.  
  35. /***************************************************************/
  36. /*                                                             */
  37. /*  DoSubst                                                    */
  38. /*                                                             */
  39. /*  Process the % escapes in the reminder.  If                 */
  40. /*  mode==NORMAL_MODE, ignore the %" sequence.  If             */
  41. /*  mode==CAL_MODE, process the %" sequence.                   */
  42. /*                                                             */
  43. /***************************************************************/
  44.  
  45. #ifdef HAVE_PROTOS
  46. PUBLIC int DoSubst(ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode)
  47. #else
  48. int DoSubst(p, out, t, tt, jul, mode)
  49. ParsePtr p;
  50. char *out;
  51. Trigger *t;
  52. TimeTrig *tt;
  53. int jul, mode;
  54. #endif
  55. {
  56.    int diff = jul - JulianToday;
  57.    int curtime = SystemTime() / 60;
  58.    int err, done;
  59.    int c;
  60.    int d, m, y;
  61.    int tim = tt->ttime;
  62.    int h, min, hh, ch, cmin, chh;
  63.    char *pm, *cpm;
  64.    int tdiff, adiff, mdiff, hdiff;
  65.    char *mplu, *hplu, *when, *plu;
  66.    int has_quote = 0;
  67.    char *s = out;
  68.    char *os;
  69.  
  70.    FromJulian(jul, &y, &m, &d);
  71.  
  72.    if (tim == NO_TIME) tim = curtime;
  73.    tdiff = tim - curtime;
  74.    adiff = ABS(tdiff);
  75.    mdiff = adiff % 60;
  76.    hdiff = adiff / 60;
  77.    mplu = (mdiff == 1 ? "" : "s");
  78.    hplu = (hdiff == 1 ? "" : "s");
  79.    when = (tdiff < 0 ? "ago" : "from now");
  80.    
  81.    h = tim / 60;
  82.    min = tim % 60;
  83.  
  84.    pm = (h < 12) ? "am" : "pm";
  85.    hh = (h == 12) ? 12 : h % 12;
  86.    
  87.    ch = curtime / 60;
  88.    cmin = curtime % 60;
  89.  
  90.    cpm = (ch < 12) ? "am" : "pm";
  91.    chh = (ch == 12) ? 12 : ch % 12;
  92.  
  93.    switch(d) {
  94.       case 1:
  95.       case 21:
  96.       case 31: plu = "st"; break;
  97.       
  98.       case 2:
  99.       case 22: plu = "nd"; break;
  100.       
  101.       case 3:
  102.       case 23: plu = "rd"; break;
  103.       
  104.       default: plu = "th"; break;
  105.    }
  106.       
  107.    
  108.    while(1) {
  109.       c = ParseChar(p, &err, 0);
  110.       if (err) return err;
  111.       if (c == '\n') continue;
  112.       if (!c) {
  113.          if (mode != CAL_MODE) *s++ = '\n';
  114.      *s++ = 0;
  115.      break;
  116.       }
  117.       if (c != '%') {
  118.          *s++ = c;
  119.      continue;
  120.       }
  121.       c = ParseChar(p, &err, 0);
  122.       if (err) return err;
  123.       if (!c) {
  124.      *s++ = 0;
  125.      break;
  126.       }
  127.       os = s;
  128.       done = 0;
  129.       if (diff <= 1) {
  130.          switch(UPPER(c)) {
  131.             case 'A':
  132.             case 'B':
  133.         case 'C':
  134.         case 'E':
  135.         case 'F':
  136.         case 'G':
  137.         case 'H':
  138.         case 'I':
  139.         case 'J':
  140.         case 'K':
  141.         case 'L':
  142.         case 'U':
  143.         case 'V': sprintf(s, "%s", (diff ? TOMORROW : TODAY));
  144.                  s += strlen(s);
  145.                  done = 1;
  146.                   break;
  147.              
  148.             default: done = 0;
  149.          }
  150.       }
  151.      
  152.       if (!done) switch(UPPER(c)) {
  153.          case 'A':
  154.             sprintf(s, "on %s, %d %s, %d", DayName[jul%7], d,
  155.             MonthName[m], y);
  156.             s += strlen(s);
  157.         break;
  158.            
  159.      case 'B':
  160.             sprintf(s, "in %d days' time", diff);
  161.         s += strlen(s);
  162.             break;
  163.            
  164.      case 'C':
  165.         sprintf(s, "on %s", DayName[jul%7]);
  166.         s += strlen(s);
  167.         break;
  168.  
  169.      case 'D':
  170.         sprintf(s, "%d", d);
  171.         s += strlen(s);
  172.         break;
  173.  
  174.      case 'E':
  175.         sprintf(s, "on %02d/%02d/%04d", d, m+1, y);
  176.         s += strlen(s);
  177.         break;
  178.  
  179.      case 'F':
  180.         sprintf(s, "on %02d/%02d/%04d", m+1, d, y);
  181.         s += strlen(s);
  182.         break;
  183.  
  184.      case 'G':
  185.         sprintf(s, "on %s, %d %s", DayName[jul%7], d, MonthName[m]);
  186.         s += strlen(s);
  187.         break;
  188.  
  189.      case 'H':
  190.         sprintf(s, "on %02d/%02d", d, m+1);
  191.         s += strlen(s);
  192.         break;
  193.  
  194.      case 'I':
  195.         sprintf(s, "on %02d/%02d", m+1, d);
  196.         s += strlen(s);
  197.         break;
  198.  
  199.      case 'J':
  200.         sprintf(s, "on %s, %s %d%s, %d", DayName[jul%7],
  201.                MonthName[m], d, plu, y);
  202.         s += strlen(s);
  203.         break;
  204.  
  205.      case 'K':
  206.         sprintf(s, "on %s, %s %d%s", DayName[jul%7],
  207.                MonthName[m], d, plu);
  208.         s += strlen(s);
  209.         break;
  210.  
  211.      case 'L':
  212.         sprintf(s, "on %04d/%02d/%02d", y, m+1, d);
  213.         s += strlen(s);
  214.         break;
  215.  
  216.      case 'M':
  217.         sprintf(s, "%s", MonthName[m]);
  218.         s += strlen(s);
  219.         break;
  220.  
  221.      case 'N':
  222.         sprintf(s, "%d", m+1);
  223.         s += strlen(s);
  224.         break;
  225.  
  226.      case 'O':
  227.         if (RealToday == JulianToday) sprintf(s, " (today)");
  228.         s += strlen(s);
  229.         break;
  230.  
  231.      case 'P':
  232.         sprintf(s, (diff == 1 ? "" : "s"));
  233.         s += strlen(s);
  234.         break;
  235.  
  236.      case 'Q':
  237.         sprintf(s, (diff == 1 ? "'s" : "s'"));
  238.         s += strlen(s);
  239.         break;
  240.  
  241.      case 'R':
  242.         sprintf(s, "%02d", d);
  243.         s += strlen(s);
  244.         break;
  245.  
  246.      case 'S':
  247.         sprintf(s, plu);
  248.         s += strlen(s);
  249.         break;
  250.  
  251.      case 'T':
  252.         sprintf(s, "%02d", m+1);
  253.         s += strlen(s);
  254.         break;
  255.  
  256.      case 'U':
  257.         sprintf(s, "on %s, %d%s %s, %d", DayName[jul%7], d,
  258.                plu, MonthName[m], y);
  259.         s += strlen(s);
  260.         break;
  261.  
  262.      case 'V':
  263.         sprintf(s, "on %s, %d%s %s", DayName[jul%7], d, plu,
  264.                MonthName[m]);
  265.         s += strlen(s);
  266.         break;
  267.  
  268.      case 'W':
  269.         sprintf(s, DayName[jul%7]);
  270.         s += strlen(s);
  271.         break;
  272.  
  273.      case 'X':
  274.         sprintf(s, "%d", diff);
  275.         s += strlen(s);
  276.         break;
  277.  
  278.      case 'Y':
  279.         sprintf(s, "%d", y);
  280.         s += strlen(s);
  281.         break;
  282.  
  283.      case 'Z':
  284.         sprintf(s, "%d", y % 100);
  285.         s += strlen(s);
  286.         break;
  287.  
  288.      case '1':
  289.         if (tdiff == 0) 
  290.            sprintf(s, "now");
  291.         else if (hdiff == 0) 
  292.            sprintf(s, "%d minute%s %s", mdiff, mplu, when);
  293.         else if (mdiff == 0)
  294.            sprintf(s, "%d hour%s %s", hdiff, hplu, when);
  295.         else
  296.            sprintf(s, "%d hour%s and %d minute%s %s", hdiff, hplu, mdiff, mplu, when);
  297.         s += strlen(s);
  298.         break;
  299.  
  300.      case '2':
  301.         sprintf(s, "at %d:%02d%s", hh, min, pm);
  302.         s += strlen(s);
  303.         break;
  304.  
  305.      case '3': sprintf(s, "at %02d:%02d", h, min);
  306.         s += strlen(s);
  307.         break;
  308.  
  309.      case '4': sprintf(s, "%d", tdiff);
  310.         s += strlen(s);
  311.         break;
  312.  
  313.      case '5': sprintf(s, "%d", adiff);
  314.         s += strlen(s);
  315.         break;
  316.  
  317.      case '6': sprintf(s, when);
  318.         s += strlen(s);
  319.         break;
  320.  
  321.      case '7': sprintf(s, "%d", hdiff);
  322.         s += strlen(s);
  323.         break;
  324.  
  325.      case '8': sprintf(s, "%d", mdiff);
  326.         s += strlen(s);
  327.         break;
  328.  
  329.      case '9': sprintf(s, mplu);
  330.         s += strlen(s);
  331.         break;
  332.  
  333.      case '0': sprintf(s, hplu);
  334.         s += strlen(s);
  335.         break;
  336.  
  337.      case '!': sprintf(s, (tdiff >= 0 ? "is" : "was"));
  338.         s += strlen(s);
  339.         break;
  340.  
  341.      case '@': sprintf(s, "%d:%02d%s", chh, cmin, cpm);
  342.         s += strlen(s);
  343.         break;
  344.  
  345.      case '#': sprintf(s, "%02d:%02d", ch, cmin);
  346.         s += strlen(s);
  347.         break;
  348.  
  349.          case '_': sprintf(s, "%s", NL);
  350.         s += strlen(s);
  351.         break;
  352.  
  353.      case QUOTE_MARKER:
  354.         /* Swallow any QUOTE_MARKERs which may somehow creep in... */
  355.         break;
  356.  
  357.      case '"':
  358.         *s++ = QUOTE_MARKER;
  359.         has_quote = 1;
  360.         break;
  361.  
  362.          default:
  363.         *s++ = c;
  364.       }
  365.       if (isupper(c)) *os = UPPER(*os);
  366.    }
  367.  
  368. /* We're outside the big while loop.  The only way to get here is for c to
  369.    be null.  Now we go through and delete %" sequences, if it's the
  370.    NORMAL_MODE, or retain only things within a %" sequence if it's the
  371.    CAL_MODE. */
  372.  
  373. /* If there are NO quotes, then:  If CAL_MODE && RUN_TYPE, we don't want the
  374.    reminder in the calendar.  Zero the output buffer and quit. */
  375.    if (!has_quote) {
  376.       if (mode == CAL_MODE && t->typ == RUN_TYPE) *out = 0;
  377.       return OK;
  378.    }
  379.  
  380. /* There ARE quotes.  If in CAL_MODE, delete everything before first quote
  381.    and after second quote.  If in NORMAL_MODE, delete the %" sequences. */
  382.  
  383.    s = out;
  384.    os = out;
  385.    if (mode == NORMAL_MODE) {
  386.       while (*s) {
  387.          if (*s != QUOTE_MARKER) *os++ = *s;
  388.      s++;
  389.       }
  390.       *os = 0;
  391.    } else {
  392.  
  393. /* Skip past the quote marker */
  394.       while (*s && (*s != QUOTE_MARKER)) s++;
  395.  
  396. /* Security check... actually, *s must == QUOTE_MARKER at this point, but
  397.    it doesn't hurt to make it a bit robust. */
  398.       if (*s) s++;
  399.  
  400. /* Copy the output until the next QUOTE_MARKER */
  401.       while (*s && (*s != QUOTE_MARKER)) *os++ = *s++;
  402.       *os = 0;
  403.    }
  404.  
  405.    return OK;
  406. }
  407.    
  408.  
  409.